package indi.zhifa.study2024.nbr.monitor.logic.curd.account.service.impl;

import indi.zhifa.core.auth.util.IAuthUtil;
import indi.zhifa.core.auth.util.ITokenUtil;
import indi.zhifa.core.common.web.entity.exception.ServiceException;
import indi.zhifa.core.mpenhance.utils.DbDtoEntityUtil;
import indi.zhifa.study2024.common.auth.enums.ERole;
import indi.zhifa.study2024.common.auth.token.AuthObject;
import indi.zhifa.study2024.common.auth.util.DatasourceSetUtil;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.po.GenBusyEnterpriseEntity;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.po.GenBusyRoleEntity;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.po.GenBusyUserEntity;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.service.IGenBusyEnterpriseDbService;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.service.IGenBusyRoleDbService;
import indi.zhifa.study2024.nbr.monitor.gen.busy.user.service.IGenBusyUserDbService;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.sys.service.IGenMonitorSysDbDbService;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.po.GenMonitorEnterpriseEntity;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.po.GenMonitorRoleEntity;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.po.GenMonitorUserEntity;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.po.json.RoleInfo;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.service.IGenMonitorEnterpriseDbService;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.service.IGenMonitorRoleDbService;
import indi.zhifa.study2024.nbr.monitor.gen.monitor.user.service.IGenMonitorUserDbService;
import indi.zhifa.study2024.nbr.monitor.logic.curd.account.entity.request.ChangePasswdRequest;
import indi.zhifa.study2024.nbr.monitor.logic.curd.account.entity.request.RegisterRequest;
import indi.zhifa.study2024.nbr.monitor.logic.curd.account.entity.request.ResetPasswdRequest;
import indi.zhifa.study2024.nbr.monitor.logic.curd.account.entity.response.RegisterResponse;
import indi.zhifa.study2024.nbr.monitor.logic.curd.account.service.IRegisterService;
import indi.zhifa.study2024.nbr.monitor.properties.AccountProperties;
import indi.zhifa.study2024.nbr.monitor.properties.ServerConfigs;
import indi.zhifa.study2024.nbr.monitor.util.DbEntityMemo;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.mybatis.spring.transaction.SpringManagedTransaction;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@RequiredArgsConstructor
@Component
public class RegisterServiceImpl implements IRegisterService {

    final IGenMonitorUserDbService mGenMonitorUserDbService;
    final IGenMonitorEnterpriseDbService mGenMonitorEnterpriseDbService;

    final IGenBusyUserDbService mGenBusyUserDbService;
    final IGenBusyEnterpriseDbService mGenBusyEnterpriseDbService;

    final IGenMonitorSysDbDbService mGenMonitorSysDbDbService;

    final IGenMonitorRoleDbService mGenMonitorRoleDbService;
    final IGenBusyRoleDbService mGenBusyRoleDbService;


    //private final RoutingDataSourceMemo mRoutingDataSourceMemo;
    private final DbEntityMemo mDbEntityMemo;

    final IAuthUtil mIAuthUtil;
    final ITokenUtil mTokenUtil;
    private final RedisTemplate<String, Object> mRedisTemplate;

    private final ServerConfigs mServConfigs;
    private final AccountProperties mAccountProperties;

    static final String ENP_CODE_PREFIX = "enp_code";


    protected void checkUserName(String pUserName) {
        GenMonitorUserEntity testUserEntity = mGenMonitorUserDbService.findByUserName(pUserName);
        if (null != testUserEntity) {
            throw new ServiceException("已存在账户名为" + pUserName + "的用户");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegisterResponse register(RegisterRequest request) {

        // 查看用户名是否重复
        checkUserName(request.getBossUserName());

        // 创建企业
        val stringObjectValueOperations = mRedisTemplate.opsForValue();
        Long id = stringObjectValueOperations.increment(ENP_CODE_PREFIX);
        String enpCode = String.valueOf(id);
        GenMonitorEnterpriseEntity monitorEnterpriseEntity = new GenMonitorEnterpriseEntity();
        monitorEnterpriseEntity.createInit();
        monitorEnterpriseEntity.setEnpCode(enpCode);
        monitorEnterpriseEntity.setEnpName(request.getEnpName());
        String dbCode = mDbEntityMemo.genDbCode();
        monitorEnterpriseEntity.setDbCode(dbCode);
        monitorEnterpriseEntity.setServCode(mServConfigs.randomServName());

        // 创建用户
        GenMonitorUserEntity monitorUserEntity = new GenMonitorUserEntity();
        monitorUserEntity.createInit();
        monitorUserEntity.setEnpId(monitorEnterpriseEntity.getId());
        monitorUserEntity.setEnpCode(enpCode);
        monitorUserEntity.setUserName(request.getBossUserName());
        String encodePasswd = mIAuthUtil.encodePasswd(request.getBossUserPassword());
        monitorUserEntity.setPasswd(encodePasswd);
        monitorUserEntity.setNickName(request.getBossNickName());


        // 设置初始用户角色
        ERole[] iniRoles = ERole.values();
        List<GenMonitorRoleEntity> genMonitorRoleEntityList = new ArrayList<>();
        GenMonitorRoleEntity bossRoleEntity = null;
        GenMonitorRoleEntity accountMgrRoleEntity = null;
        for (ERole role : iniRoles) {
            GenMonitorRoleEntity genMonitorRoleEntity = new GenMonitorRoleEntity();
            genMonitorRoleEntity.createInit();
            genMonitorRoleEntity.setEnpId(monitorEnterpriseEntity.getId());
            genMonitorRoleEntity.setEnpCode(enpCode);
            genMonitorRoleEntity.setCode(role.getCode());
            genMonitorRoleEntity.setName(role.getName());
            genMonitorRoleEntity.setDescription(role.getDesc());
            genMonitorRoleEntityList.add(genMonitorRoleEntity);
            if (role == ERole.BOSS) {
                bossRoleEntity = genMonitorRoleEntity;
            } else if (role == ERole.ACCOUNT_MGR) {
                accountMgrRoleEntity = genMonitorRoleEntity;
            }
        }
        RoleInfo bossRoleInfo = new RoleInfo();
        bossRoleInfo.setId(bossRoleEntity.getId());
        bossRoleInfo.setCode(bossRoleEntity.getCode());
        bossRoleInfo.setName(bossRoleEntity.getName());

        RoleInfo accountMgrRoleInfo = new RoleInfo();
        accountMgrRoleInfo.setId(accountMgrRoleEntity.getId());
        accountMgrRoleInfo.setCode(accountMgrRoleEntity.getCode());
        accountMgrRoleInfo.setName(accountMgrRoleEntity.getName());

        monitorUserEntity.setRoles(Arrays.asList(bossRoleInfo, accountMgrRoleInfo));

        // 存储
        SpringManagedTransaction s;

        mGenMonitorEnterpriseDbService.save(monitorEnterpriseEntity);
        mGenMonitorUserDbService.save(monitorUserEntity);
        mGenMonitorRoleDbService.saveBatch(genMonitorRoleEntityList);


        // 在企业中心，在同步存储一份

        DatasourceSetUtil.setDbPrompt(dbCode);
        GenBusyEnterpriseEntity busyEnterpriseEntity = DbDtoEntityUtil.trans(monitorEnterpriseEntity, GenBusyEnterpriseEntity.class);
        mGenBusyEnterpriseDbService.save(busyEnterpriseEntity);
        GenBusyUserEntity busyUserEntity = DbDtoEntityUtil.trans(monitorUserEntity, GenBusyUserEntity.class);
        mGenBusyUserDbService.save(busyUserEntity);
        List<GenBusyRoleEntity> iniRoleEntities = DbDtoEntityUtil.trans(genMonitorRoleEntityList, GenBusyRoleEntity.class);
        mGenBusyRoleDbService.saveBatch(iniRoleEntities);

        RegisterResponse rtn = new RegisterResponse();
        rtn.setEnterpriseInfo(monitorEnterpriseEntity);
        rtn.setUserInfo(monitorUserEntity);
        rtn.setInitRoleList(genMonitorRoleEntityList);

        DatasourceSetUtil.clear();

        return rtn;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean changePasswd(ChangePasswdRequest request) {
        AuthObject authObject = mTokenUtil.getAuthObject();
        Long userId = authObject.getUserId();
        GenMonitorUserEntity monitorUserEntity = mGenMonitorUserDbService.getById(userId);
        if (!mIAuthUtil.passwdMatch(request.getPasswdOrg(), monitorUserEntity.getPasswd())) {
            throw new ServiceException("输入的密码不正确");
        }
        String newEncodePasswd = mIAuthUtil.encodePasswd(request.getPasswdNew());
        monitorUserEntity.setPasswd(newEncodePasswd);
        mGenMonitorUserDbService.updateById(monitorUserEntity);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String resetPasswd(ResetPasswdRequest request) {
        AuthObject authObject = mTokenUtil.getAuthObject();
        Long userId = authObject.getUserId();
        GenMonitorUserEntity monitorUserEntity = mGenMonitorUserDbService.getById(userId);
        String newEncodePasswd = mIAuthUtil.encodePasswd(mAccountProperties.getDefaultPasswd());
        monitorUserEntity.setPasswd(newEncodePasswd);
        mGenMonitorUserDbService.updateById(monitorUserEntity);
        return mAccountProperties.getDefaultPasswd();
    }

}
